﻿using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using MyLib.Web;

namespace MyLib.Web.UI {
	/// <summary>
	/// 
	/// </summary>
	[DefaultProperty("Value")]
	[ToolboxData("<{0}:MyTextLine runat=\"server\" ></{0}:MyTextLine>")]
	public class MyTextLine : WebControl, ITextControl {
		/// <summary>
		/// 
		/// </summary>
		private const int DefaultValueScale = 1;

		#region ITextControl

		/// <summary>
		/// 
		/// </summary>
		[Category("Appearance")]
		[Bindable(true, BindingDirection.TwoWay)]
		[Browsable(true)]
		public string Text {
			get {
				var obj = Value == null ? "" : Value;

				System.Diagnostics.Debug.Assert(obj != null);

				switch (TextFormat) {
					case TextFormat.Plain:
						return FormatValue("{0}", obj);
					case TextFormat.Integer:
						if (ValueScale != 1) {
							if (string.IsNullOrWhiteSpace(Convert.ToString(obj))) {
								return string.Empty;
							} else {
								int c;
								try {
									c = Convert.ToInt32(obj) / ValueScale;
								} catch (Exception ce) {
									throw new InvalidCastException(
										string.Format(@"Invalid interger value ""{0}"" of ""{1}"".", obj, UniqueID), ce);
								}
								return FormatValue("{0:D}", c);
							}
						} else {
							return FormatValue("{0:D}", obj);
						}
					case TextFormat.Double:
						if (ValueScale != 1) {
							if (string.IsNullOrWhiteSpace(Convert.ToString(obj))) {
								return string.Empty;
							} else {
								double c;
								try {
									c = Convert.ToDouble(obj) / ValueScale;
								} catch (Exception ce) {
									throw new InvalidCastException(
										string.Format(@"Invalid double value ""{0}"" of ""{1}"".", obj, UniqueID), ce);
								}
								return FormatValue("{0:N2}", c);
							}
						} else {
							return FormatValue("{0:N2}", obj);
						}
					case TextFormat.Currency:
						if (ValueScale != 1) {
							if (string.IsNullOrWhiteSpace(Convert.ToString(obj))) {
								return string.Empty;
							} else {
								decimal c;
								try {
									c = Convert.ToDecimal(obj) / ValueScale;
								} catch (Exception ce) {
									throw new InvalidCastException(
										string.Format(@"Invalid currency value ""{0}"" of ""{1}"".", obj, UniqueID), ce);
								}
								return FormatValue("{0:N2}", c);
							}
						} else {
							return FormatValue("{0:N2}", obj);
						}
					case TextFormat.Percent:
						return FormatValue("{0:0.##}%", obj);
					case TextFormat.Date:
						return FormatValue("{0:yyyy-M-d}", obj);
					case TextFormat.DateTime:
						return FormatValue("{0:yyyy-M-d H:mm}", obj);
					case TextFormat.Time:
						return FormatValue("{0:H:mm}", obj);
					case TextFormat.YearMonth:
						return FormatValue("{0:yyyy-M}", obj);
					case TextFormat.Email:
						return FormatValue("{0}", obj);
					case TextFormat.Website:
						var t1 = obj.ToString().Trim();
						if (
							!t1.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
							!t1.StartsWith("https://", StringComparison.OrdinalIgnoreCase) &&
							!t1.StartsWith("ftp://", StringComparison.OrdinalIgnoreCase)) {
							t1 = string.Concat("http://", t1);
						}

						return FormatValue("{0}", t1);
					default:
						System.Diagnostics.Debug.Assert(false, "Unknown text format: " + TextFormat);
						return "";
				}
			} // end of get.
			set {
				var obj = value == null ? "" : value;

				System.Diagnostics.Debug.Assert(obj != null);

				switch (TextFormat) {
					case TextFormat.Plain:
						Value = obj;
						break;
					case TextFormat.Integer:
						if (string.IsNullOrWhiteSpace(obj)) {
							Value = (int?)null;
						} else {
							int o;
							if (int.TryParse(obj.Trim(), out o)) {
								if (ValueScale != 1) {
									Value = o * ValueScale;
								} else {
									Value = o;
								}
							}
						}
						break;
					case TextFormat.Double:
						if (string.IsNullOrWhiteSpace(obj)) {
							Value = (double?)null;
						} else {
							double o;
							if (double.TryParse(obj.Trim(), out o)) {
								if (ValueScale != 1) {
									Value = o * ValueScale;
								} else {
									Value = o;
								}
							}
						}
						break;
					case TextFormat.Currency:
						if (string.IsNullOrWhiteSpace(obj)) {
							Value = (decimal?)null;
						} else {
							decimal o;
							if (decimal.TryParse(obj.Trim(), out o)) {
								if (ValueScale != 1) {
									Value = o * ValueScale;
								} else {
									Value = o;
								}
							}
						}
						break;
					case TextFormat.Percent:
						var peri = obj.IndexOf('%');
						if (peri != -1) {
							obj = obj.Substring(0, peri);
						}

						if (string.IsNullOrWhiteSpace(obj)) {
							Value = (double?)null;
						} else {
							double o;
							if (double.TryParse(obj.Trim(), out o)) {
								Value = o;
							}
						}
						break;
					case TextFormat.Date:
						if (string.IsNullOrWhiteSpace(obj)) {
							Value = (DateTime?)null;
						} else {
							DateTime o;
							if (DateTime.TryParse(obj.Trim(), out o)) {
								Value = o;
							}
						}
						break;
					case TextFormat.DateTime:
						if (string.IsNullOrWhiteSpace(obj)) {
							Value = (DateTime?)null;
						} else {
							DateTime o;
							if (DateTime.TryParse(obj.Trim(), out o)) {
								Value = o;
							}
						}
						break;
					case TextFormat.Time:
						if (string.IsNullOrWhiteSpace(obj)) {
							Value = (DateTime?)null;
						} else {
							TimeSpan o;
							if (TimeSpan.TryParse(obj.Trim(), out o)) {
								Value = o;
							}
						}
						break;
					case TextFormat.YearMonth:
						if (string.IsNullOrWhiteSpace(obj)) {
							Value = (DateTime?)null;
						} else {
							DateTime o;
							if (DateTime.TryParse(obj.Trim(), out o)) {
								Value = o;
							}
						}
						break;
					case TextFormat.Email:
						Value = obj.Trim();
						break;
					case TextFormat.Website:
						obj = obj.Trim();
						if (
							!obj.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
							!obj.StartsWith("https://", StringComparison.OrdinalIgnoreCase) &&
							!obj.StartsWith("ftp://", StringComparison.OrdinalIgnoreCase)) {
							obj = string.Concat("http://", obj);
						}
						Value = obj;
						break;
					default:
						System.Diagnostics.Debug.Assert(false, "Unknown textmode: " + TextFormat);
						break;
				}
			} // end of set.
		}

		#endregion

		/// <summary>
		/// 
		/// </summary>
		[Category("Appearance")]
		[Bindable(false)]
		[Browsable(true)]
		public TextFormat TextFormat {
			get {
				var obj = ViewState["TextFormat"];
				if (obj == null) {
					return TextFormat.Plain;
				} else {
					return (TextFormat)obj;
				}
			}
			set {
				ViewState["TextFormat"] = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[Category("Appearance")]
		[Bindable(true)]
		[Browsable(true)]
		[DefaultValue(DefaultValueScale)]
		public int ValueScale {
			get {
				var obj = ViewState["ValueScale"];
				if (obj == null) {
					return DefaultValueScale;
				} else {
					return (int)obj;
				}
			}
			set {
				ViewState["ValueScale"] = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[Category("Appearance")]
		[Bindable(false)]
		[Browsable(true)]
		[DefaultValue("")]
		public string CustomFormat {
			get {
				var obj = ViewState["CustomeFormat"];
				if (obj == null) {
					return "";
				} else {
					return (string)obj;
				}
			}
			set {
				ViewState["CustomeFormat"] = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[Bindable(true, BindingDirection.TwoWay)]
		[Browsable(true)]
		public object Value {
			get {
				var ret = ViewState["Value"];
				return ret == null ? "" : ret;
			}
			set {
				ViewState["Value"] = value == null ? "" : value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		[Category("Appearance")]
		[Bindable(false)]
		[Browsable(true)]
		[DefaultValue(0)]
		public int Size {
			get {
				var obj = ViewState["Size"];
				if (obj == null) {
					return 0;
				} else {
					return (int)obj;
				}
			}
			set {
				if (value < 0) {
					ViewState["Size"] = 0;
				} else {
					ViewState["Size"] = value;
				}
			}
		} // end of Size.

		/// <summary>
		/// 
		/// </summary>
		/// <param name="format"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		private string FormatValue(string format, object value) {
			return string.Format(string.IsNullOrWhiteSpace(CustomFormat) ? format : CustomFormat, value);
		} // end of FormatValue.

		/// <summary>
		/// 
		/// </summary>
		/// <param name="writer"></param>
		protected override void Render(HtmlTextWriter writer) {
			var text = Text;

			var ctext = "";
			if (Size > 0 && text.Length > Size) {
				ctext = HtmlUtility.CutDown(text, Size);
			} else {
				ctext = text;
			}

			System.Diagnostics.Debug.Assert(Text != null);

			AddAttributesToRender(writer);

			if (string.IsNullOrWhiteSpace(ToolTip) && text.Length != 0) {
				writer.AddAttribute(HtmlTextWriterAttribute.Title, text);
			}

			if (TextFormat == TextFormat.Email || TextFormat == TextFormat.Website) {
				writer.AddAttribute(HtmlTextWriterAttribute.Href,
					TextFormat == TextFormat.Email ? string.Concat("mailto://", text) :
					text);
				writer.RenderBeginTag(HtmlTextWriterTag.A);
			} else {
				writer.RenderBeginTag(HtmlTextWriterTag.Span);
			}


			System.Web.HttpUtility.HtmlEncode(ctext.Length == 0 ? "\xa0" : ctext, writer);

			writer.RenderEndTag();
		} // end of Render.
	} // end of MyText.

	/// <summary>
	/// 
	/// </summary>
	public enum TextFormat {
		/// <summary>
		/// Plain text.
		/// </summary>
		Plain = 1,

		/// <summary>
		/// Integer.
		/// </summary>
		Integer,

		/// <summary>
		/// Double.
		/// </summary>
		Double,

		/// <summary>
		/// Currency.
		/// </summary>
		Currency,

		/// <summary>
		/// Precent.
		/// </summary>
		Percent,

		/// <summary>
		/// Date.
		/// </summary>
		Date,

		/// <summary>
		/// DateTime.
		/// </summary>
		DateTime,

		/// <summary>
		/// Time.
		/// </summary>
		Time,

		/// <summary>
		/// YearMonth.
		/// </summary>
		YearMonth,

		/// <summary>
		/// Email.
		/// </summary>
		Email,

		/// <summary>
		/// Website.
		/// </summary>
		Website
	} // end of MyTextMode.
}
